﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeBuilder.Service
{
    public class CreateService
    {
        private string tableName;
        private string fileDir;
        private DataTable dataTable;
        private DataTable indexTable;
        public CreateService(string tableName, string fileDir, DataTable dataTable, DataTable indexTable)
        {
            this.tableName = tableName;
            this.fileDir = fileDir;
            this.dataTable = dataTable;
            this.indexTable = indexTable;
        }

        public void Run()
        {
            var dataRows = new List<DataRow>();
            foreach (DataRow row in this.dataTable.Rows)
            {
                dataRows.Add(row);
            }
            var indexRows = new List<DataRow>();
            foreach (DataRow row in this.indexTable.Rows)
            {
                indexRows.Add(row);
            }
            var formatTableName = Helper.GetPascalCase(tableName).Substring(1);
            var dtoName = $"{formatTableName}Dto";
            var privateDtoName = Helper.GetCamelCase(dtoName);
            var entityName = $"{Helper.GetPascalCase(tableName)}Entity";
            var privateEntityName = Helper.GetCamelCase(entityName);
            var privateEntitiesName = Helper.GetCamelCase($"{Helper.GetPascalCase(tableName)}Entities");
            var iRepository = $"I{Helper.GetPascalCase(tableName)}Repository";
            var privateIReporty = Helper.GetCamelCase(iRepository.Substring(1));
            var fileName = $"{formatTableName}Service";
            IList<string> contents = new List<string>();
            contents.Add($"using Hualong.TestWorldPro.Common;");
            contents.Add($"using Hualong.TestWorldPro.Dto;");
            contents.Add($"using Hualong.TestWorldPro.Entities;");
            contents.Add($"using Hualong.TestWorldPro.Repository;");
            contents.Add($"using Hualong.TestWorldPro.Repository.{Helper.GetPascalCase(tableName)};");
            contents.Add($"using Microsoft.Extensions.Logging;");
            contents.Add($"");
            contents.Add($"namespace Hualong.TestWorldPro.Services.{formatTableName}");
            contents.Add("{");
            contents.Add($"    public partial class {formatTableName}Service : BaseService, I{formatTableName}Service");
            contents.Add("    {");
            contents.Add($"        private readonly {iRepository} {privateIReporty};");
            contents.Add($"        public {fileName}(");
            contents.Add($"            {iRepository} {privateIReporty},");
            contents.Add($"            IBaseRepository baseRepository, ");
            contents.Add($"            ILogger<{fileName}> logger) : base(baseRepository, logger)");
            contents.Add("        {");
            contents.Add($"            this.{privateIReporty} = {privateIReporty};");
            contents.Add("        }");
            var indexRowGroups = indexRows.GroupBy(xx => xx[2].ToString()).ToList();
            foreach (var indexRowGroup in indexRowGroups)
            {
                if (indexRowGroup.Count() == 1 && indexRowGroup.FirstOrDefault()[4].ToString() == "id")
                    continue;
                var rows = indexRowGroup.OrderBy(xx => xx[3]).ToList();
                string methodName = string.Empty;
                string parasName = string.Empty;
                string paras =string.Empty;
                string returnName = string.Empty;
                string mapperName = string.Empty;
                string complex = string.Empty;
                for (int i = 0; i < rows.Count; i++)
                {
                    DataRow field = dataRows.FirstOrDefault(xx => xx[0].ToString() == rows[i][4].ToString());
                    methodName += $"{Helper.GetPascalCase(rows[i][4].ToString())}";
                    parasName += $"{DataTypeMap.Get(field[1].ToString())} {Helper.GetCamelCase(rows[i][4].ToString())}";
                    paras += $"{Helper.GetCamelCase(rows[i][4].ToString())}";
                    if (i < rows.Count - 1)
                    {
                        methodName += "And";
                        parasName += ", ";
                        paras += ", ";
                    }
                }
                if (rows.FirstOrDefault()[1].ToString() == "0")
                {
                    returnName = $"Task<{dtoName}>";
                    mapperName = $"MapperTo";
                }
                else
                {
                    returnName = $"Task<IList<{dtoName}>>";
                    mapperName = $"MappersTo";
                    complex = "s";
                }
                contents.Add($"        public async {returnName} GetBy{methodName}Async({parasName})");
                contents.Add("        {");
                contents.Add($"            var result = await this.{privateIReporty}.GetItem{complex}By{methodName}Async({paras});");
                contents.Add($"            return result.{mapperName}<{entityName}, {dtoName}>();");
                contents.Add("        }");
                //delete
                contents.Add($"        public async Task<int> DeleteBy{methodName}Async({parasName})");
                contents.Add("        {");
                contents.Add($"            return await this.{privateIReporty}.Delete{complex}By{methodName}Async({paras});");
                contents.Add("        }");
            }
            contents.Add($"        public async Task<{dtoName}> GetByIdAsync(long id)");
            contents.Add("        {");
            contents.Add($"            var {privateEntityName} = await this.{privateIReporty}.GetItemAsync(id);");
            contents.Add($"            return {privateEntityName}.MapperTo<{entityName}, {dtoName}>();");
            contents.Add("        }");
            contents.Add($"        public async Task<IList<{dtoName}>> GetAllAsync()");
            contents.Add("        {");
            contents.Add($"            var result = await {privateIReporty}.GetItemsAsync();");
            contents.Add($"            return result.MappersTo<{entityName}, {dtoName}>();");
            contents.Add("        }");
            contents.Add($"        public async Task<int> SaveAsync({dtoName} {privateDtoName})");
            contents.Add("        {");
            contents.Add($"            if ({privateDtoName}.Id > 0)");
            contents.Add("            {");
            contents.Add($"                var {privateEntityName} = {privateDtoName}.MapperTo<{dtoName}, {entityName}>();");
            contents.Add($"                {privateEntityName}.UpdateUser = LoginHelper.CurrentUser;");
            contents.Add($"                {privateEntityName}.UpdateTime = DateTime.Now;");
            contents.Add($"                return await this.{privateIReporty}.UpdateAsync({privateEntityName});");
            contents.Add("            }");
            contents.Add($"            else");
            contents.Add("            {");
            contents.Add($"                var {privateEntityName} = {privateDtoName}.MapperTo<{dtoName}, {entityName}>();");
            contents.Add($"                {privateEntityName}.UpdateUser = LoginHelper.CurrentUser;");
            contents.Add($"                {privateEntityName}.UpdateTime = DateTime.Now;");
            contents.Add($"                {privateEntityName}.CreateUser = LoginHelper.CurrentUser;");
            contents.Add($"                {privateEntityName}.CreateTime = DateTime.Now;");
            contents.Add($"                return await this.{privateIReporty}.InsertAsync({privateEntityName});");
            contents.Add("            }");
            contents.Add("        }");
            contents.Add($"        public async Task<int> SaveAsync(IList<{dtoName}> {privateDtoName}s)");
            contents.Add("        {");
            contents.Add("            int result = 0;");
            contents.Add($"            if ({privateDtoName}s?.Count > 0)");
            contents.Add("            {");
            contents.Add($"                var {privateEntitiesName} = {privateDtoName}s.MappersTo<{dtoName}, {entityName}>();");
            contents.Add($"                {privateEntitiesName}.ForEach(t =>");
            contents.Add("                {");
            contents.Add($"                    t.UpdateUser = LoginHelper.CurrentUser;");
            contents.Add($"                    t.UpdateTime = DateTime.Now;");
            contents.Add($"                    if (t.Id <= 0)");
            contents.Add("                    {");
            contents.Add($"                        t.CreateUser = LoginHelper.CurrentUser;");
            contents.Add($"                        t.CreateTime = DateTime.Now;");
            contents.Add("                    }");
            contents.Add("                });");
            contents.Add($"                if ({privateEntitiesName}.Any(xx => xx.Id <= 0))");
            contents.Add("                {");
            contents.Add($"                    var insertCount = await this.{privateIReporty}.InsertAllAsync({privateEntitiesName}.Where(xx => xx.Id <= 0));");
            contents.Add($"                    result += insertCount;");
            contents.Add("                }");
            contents.Add($"                if ({privateEntitiesName}.Any(xx => xx.Id > 0))");
            contents.Add("                {");
            contents.Add($"                    var updateCount = await this.{privateIReporty}.UpdateAllAsync({privateEntitiesName}.Where(xx => xx.Id > 0));");
            contents.Add($"                    result += updateCount;");
            contents.Add("                }");
            contents.Add("            }");
            contents.Add($"            return result;");
            contents.Add("        }");
            contents.Add($"        public async Task<int> DeleteByIdAsync(long id)");
            contents.Add("        {");
            contents.Add($"            var {privateEntityName} = await this.{privateIReporty}.GetItemAsync(id);");
            contents.Add($"            if ({privateEntityName} != null && {privateEntityName}.Id > 0)");
            contents.Add("            {");
            contents.Add($"                return await this.{privateIReporty}.DeleteItemAsync({privateEntityName});");
            contents.Add("            }");
            contents.Add($"            return 0;");
            contents.Add("        }");
            contents.Add($"        public async Task<int> LogicalDeleteByIdAsync(long id)");
            contents.Add("        {");
            contents.Add($"            var {privateEntityName} = await this.{privateIReporty}.GetItemAsync(id);");
            contents.Add($"            if ({privateEntityName} != null && {privateEntityName}.Id > 0)");
            contents.Add("            {");
            contents.Add($"                {privateEntityName}.UpdateUser = LoginHelper.CurrentUser;");
            contents.Add($"                {privateEntityName}.UpdateTime = DateTime.Now;");
            contents.Add($"                {privateEntityName}.IsDeleted = true;");
            contents.Add($"                return await this.{privateIReporty}.UpdateAsync({privateEntityName});");
            contents.Add("            }");
            contents.Add($"            return 0;");
            contents.Add("        }");
            contents.Add("    }");
            contents.Add("}");
            string filePath = Path.Combine(fileDir, formatTableName);
            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }
            filePath = Path.Combine(filePath, $"{fileName}.cs");
            if (File.Exists(filePath))
            { File.Delete(filePath); }
            File.WriteAllLines(filePath, contents, Encoding.UTF8);

            Console.WriteLine($"创建:{filePath} 完成！");
        }
    }
}
